from datetime import datetime

from flask import Blueprint, request, current_app, g
from util.permission import permission_required
from util.result import Result
from models import db, Book

# 创建图书管理的蓝图
api_bp = Blueprint('book', __name__)


# 1. 创建图书接口（需要book:create权限）
@api_bp.route('/book', methods=['POST'])
@permission_required('book:create')
def create_book():
    try:
        data = request.get_json()
        if not data:
            return Result.error("请输入图书信息")

        # 验证必填字段
        required_fields = ['isbn', 'name', 'author', 'publisher', 'category']
        for field in required_fields:
            if field not in data or not str(data[field]).strip():
                return Result.error(f"{field} 是必填项")

        # 处理输入数据（去除首尾空格）
        isbn = str(data['isbn']).strip()
        name = str(data['name']).strip()
        author = str(data['author']).strip()
        publisher = str(data['publisher']).strip()
        category = ','.join(data['category'])

        # 检查图书ISBN编号是否已存在
        if Book.query.filter_by(isbn=isbn).first():
            return Result.error("图书ISBN编号已存在")

        # 创建新图书
        new_book = Book(
            isbn=isbn,
            name=name,
            author=author,
            publisher=publisher,
            category=category,
            created_at=datetime.now(),
            updated_at=datetime.now()
        )

        db.session.add(new_book)
        db.session.commit()

        return Result.success("图书创建成功")

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"创建图书异常: {str(e)}")
        return Result.error("创建图书失败，请稍后重试")


# 2. 分页查询图书接口（需要book:read权限，支持筛选、排序）
@api_bp.route('/book', methods=['GET'])
@permission_required('book:read')
def search_book():
    try:
        # 1. 获取分页参数（默认第1页，每页10条）
        page = request.args.get('page', type=int)  # 当前页码
        size = request.args.get('size', type=int)  # 每页条数
        # 页码和条数合法性校验
        if page < 1:
            page = 1
        if size < 1 or size > 100:  # 限制最大每页100条，避免性能问题
            size = 10

        # 2. 获取筛选参数
        kw = request.args.get('kw').strip()  # 名称模糊筛选
        category = request.args.get('category').strip()

        # 3. 构建查询条件
        query = Book.query
        if kw:
            query = query.filter((Book.isbn.like(f"%{kw}%") | (
                    Book.name.like(f"%{kw}%") | (Book.author.like(f"%{kw}%")) | (Book.publisher.like(f"%{kw}%")))))

        if category and category != 'all':
            query = query.filter(Book.category.like(f"%{category}%"))

        # 4. 构建排序条件（默认按创建时间倒序）
        query = query.order_by(Book.created_at.desc())

        # 5. 执行分页查询（SQLAlchemy内置分页方法）
        paginated_result = query.paginate(page=page, per_page=size, error_out=False)
        # 获取当前页数据
        books = paginated_result.items

        # 6. 格式化返回数据
        result_list = [{
            "id": book.id,
            "isbn": book.isbn,
            "name": book.name,
            "author": book.author,
            "publisher": book.publisher,
            "category": book.category.split(','),
            "created_at": book.created_at.strftime("%Y-%m-%d %H:%M:%S"),
            "updated_at": book.updated_at.strftime("%Y-%m-%d %H:%M:%S")
        } for book in books]

        # 7. 构建分页响应体（包含分页元信息，方便前端渲染分页组件）
        page_data = {
            "total": paginated_result.total,  # 总记录数
            "page": page,  # 当前页码
            "size": size,  # 每页条数
            "list": result_list  # 当前页数据列表
        }

        return Result.success("分页查询成功", data=page_data)

    except Exception as e:
        current_app.logger.error(f"图书分页查询异常: {str(e)}")
        return Result.error("分页查询图书失败，请稍后重试")

# 3. 更新图书接口（需要book:edit权限）
@api_bp.route('/book', methods=['PUT'])
@permission_required('book:update')
def update_book():
    try:
        data = request.get_json()
        if not data:
            return Result.error("请输入更新信息")

        # 必须提供id才能更新
        book_id = data.get('id')
        if not book_id:
            return Result.error("请提供图书ID")

        # 查询指定ID的图书
        book = Book.query.get(book_id)
        if not book:
            return Result.error("未找到指定图书")

        # 检查图书ISBN编号是否重复
        if 'isbn' in data and data['isbn'] is not None:
            new_isbn = str(data['isbn']).strip()
            # 排除当前图书ID，检查是否有同名图书
            existing = Book.query.filter(
                book.isbn == new_isbn,
                book.id != book_id
            ).first()
            if existing:
                return Result.error("图书ISBN编号已存在")
            book.isbn = new_isbn

        book.name = str(data['name']).strip()
        book.author = str(data['author']).strip()
        book.publisher = str(data['publisher']).strip()
        book.category = ','.join(data['category'])
        # 修改图书的更新时间
        book.updated_at = datetime.now()

        db.session.commit()
        return Result.success("图书更新成功")

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"更新图书异常: {str(e)}")
        return Result.error("更新图书失败，请稍后重试")


# 4. 删除图书接口（需要book:delete权限）
@api_bp.route('/book/<int:book_id>', methods=['DELETE'])
@permission_required('book:delete')
def delete_book(book_id):
    try:
        book = Book.query.get(book_id)
        if not book:
            return Result.error("图书不存在")

        db.session.delete(book)
        db.session.commit()

        return Result.success("图书删除成功")

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"删除图书异常: {str(e)}")
        return Result.error("删除图书失败，请稍后重试")

# 5. 获取全部图书接口（需要book:read权限）
@api_bp.route('/book/all', methods=['GET'])
@permission_required('book:read')
def all_book():
    try:
        data = [{
            "value": book.id,
            "label": book.name,
        } for book in Book.query.all()]
        return Result.success(data=data)

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"获取全部图书数据异常: {str(e)}")
        return Result.error("获取全部图书数据失败，请稍后重试")